package openrr.geom;
//imports
import static org.lwjgl.opengl.GL11.*;


import java.io.FileInputStream;
import java.io.IOException;
import java.util.Vector;

import openrr.gl.Texture;

//a texture group is a group of geometry that all has the same texture
public class TextureGroup {
	//these vectors hold the geometry data. xCoord - zCoords is for the vertices, and texXCoords & texYCoords are for the texture coordinates
	private Vector<Float> xCoords = new Vector<Float>();
	private Vector<Float> yCoords = new Vector<Float>();
	private Vector<Float> zCoords = new Vector<Float>();
	private Vector<Float> texXCoords = new Vector<Float>();
	private Vector<Float> texYCoords = new Vector<Float>();
	//holds the texture of the group
	private Texture tex;
	
	public TextureGroup(String textureSrc)
	{
		//System.out.println("adding texture group from: " + textureSrc);
		//loads the texture (using the slick 2D library)
		Texture texture = new Texture(textureSrc);
		this.tex = texture;
	}
	//adds a vertex to the texture group
	public void addVertex(float xCoord, float yCoord, float zCoord, float texXCoord, float texYCoord)
	{
		this.xCoords.add(xCoord);
		this.yCoords.add(yCoord);
		this.zCoords.add(zCoord);
		this.texXCoords.add(texXCoord);
		this.texYCoords.add(texYCoord);
	}
	//adds a cube to the texture group. This function is used by the map builder to build the map. putting the function here allows easy debugging
	public void addCube(int x, int y, int z, int width)
	{
		//bottom
		this.addVertex(x - width, y - width, z, 0, 0);
		this.addVertex(x + width, y - width, z, 1, 0);
		this.addVertex(x + width, y + width, z, 1, 1);
		this.addVertex(x - width, y - width, z, 0, 0);
		this.addVertex(x + width, y + width, z, 1, 1);
		this.addVertex(x - width, y + width, z, 0, 1);
		
		//top
		this.addVertex(x - width, y - width, z + 2*width, 0, 0);
		this.addVertex(x + width, y - width, z + 2*width, 1, 0);
		this.addVertex(x + width, y + width, z + 2*width, 1, 1);
		this.addVertex(x - width, y - width, z + 2*width, 0, 0);
		this.addVertex(x + width, y + width, z + 2*width, 1, 1);
		this.addVertex(x - width, y + width, z + 2*width, 0, 1);
		
		//front
		this.addVertex(x - width, y - width, z, 0, 0);
		this.addVertex(x + width, y - width, z, 1, 0);
		this.addVertex(x + width, y - width, z + 2*width, 1, 1);
		this.addVertex(x - width, y - width, z, 0, 0);
		this.addVertex(x + width, y - width, z + 2*width, 1, 1);
		this.addVertex(x - width, y - width, z + 2*width, 0, 1);
		
		//right
		this.addVertex(x + width, y - width, z, 0, 0);
		this.addVertex(x + width, y + width, z, 1, 0);
		this.addVertex(x + width, y + width, z + 2*width, 1, 1);
		this.addVertex(x + width, y - width, z, 0, 0);
		this.addVertex(x + width, y + width, z + 2*width, 1, 1);
		this.addVertex(x + width, y - width, z + 2*width, 0, 1);
		
		//back
		this.addVertex(x + width, y + width, z, 0, 0);
		this.addVertex(x - width, y + width, z, 1, 0);
		this.addVertex(x - width, y + width, z + 2*width, 1, 1);
		this.addVertex(x + width, y + width, z, 0, 0);
		this.addVertex(x - width, y + width, z + 2*width, 1, 1);
		this.addVertex(x + width, y + width, z + 2*width, 0, 1);
		
		//left
		this.addVertex(x - width, y + width, z, 0, 0);
		this.addVertex(x - width, y - width, z, 1, 0);
		this.addVertex(x - width, y - width, z + 2*width, 1, 1);
		this.addVertex(x - width, y + width, z, 0, 0);
		this.addVertex(x - width, y - width, z + 2*width, 1, 1);
		this.addVertex(x - width, y + width, z + 2*width, 0, 1);
	}
	public void addPlane(int x, int y, int size, int height)
	{
		this.addVertex((float)(x - size/2), (float)(y + size/2), (float)height, 0f, 0f);
		this.addVertex((float)(x - size/2), (float)(y - size/2), (float)height, 0f, 1f);
		this.addVertex((float)(x + size/2), (float)(y - size/2), (float)height, 1f, 1f);
		this.addVertex((float)(x - size/2), (float)(y + size/2), (float)height, 0f, 0f);
		this.addVertex((float)(x + size/2), (float)(y - size/2), (float)height, 1f, 1f);
		this.addVertex((float)(x + size/2), (float)(y + size/2), (float)height, 1f, 0f);
	}
	
	public void addBasicWall(String direction, int x, int y, int size, int bottom, int height)
	{
		if(direction.equals("west"))
		{
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)bottom, 0f, 1f);
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)height, 1f, 0f);
		} else if(direction.equals("south"))
		{
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)bottom, 0f, 1f);
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)height, 1f, 0f);
		} else if(direction.equals("north"))
		{
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)bottom, 0f, 1f);
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)height, 1f, 0f);
		} else if(direction.equals("east"))
		{
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)bottom, 0f, 1f);
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)height, 1f, 0f);
		} 
	}
	
	public void addCorneredWall(String direction, int x, int y, int size, int bottom, int height)
	{
		//arrayX = [1, 1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1]
		//arrayY = [1, -1, -1, 1, 1, -1, -1, 1, 1, -1, -1, 1]
		
		if(direction.equals("west"))
		{
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)bottom, 0f, 1f);
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)bottom, 0f, 1f);
		} else if(direction.equals("south"))
		{
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)bottom, 0f, 1f);
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)bottom, 0f, 1f);
		} else if(direction.equals("north"))
		{
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)bottom, 0f, 1f);
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)bottom, 0f, 1f);
		} else if(direction.equals("east"))
		{
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)bottom, 0f, 1f);
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)bottom, 0f, 1f);
		} 
	}
	
	public void addInvertedWall(String direction, int x, int y, int size, int bottom, int height)
	{
		if(direction.equals("west"))
		{
			//System.out.println("buidling inverted wall west");
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)height, 0f, 1f);
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)height, 1f, 0f);
		} else if(direction.equals("south"))
		{
			//System.out.println("buidling inverted wall south");
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)height, 0f, 1f);
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)height, 1f, 0f);
		} else if(direction.equals("north"))
		{
			//System.out.println("buidling inverted wall north");
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)height, 0f, 1f);
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)height, 1f, 0f);
		} else if(direction.equals("east"))
		{
			//System.out.println("buidling inverted wall east");
			
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x + size/2), (float)(y + size/2), (float)height, 0f, 1f);
			this.addVertex((float)(x + size/2), (float)(y - size/2), (float)height, 0f, 0f);
			this.addVertex((float)(x - size/2), (float)(y + size/2), (float)bottom, 1f, 1f);
			this.addVertex((float)(x - size/2), (float)(y - size/2), (float)height, 1f, 0f);
		} 
	}
	
	//draws the texture group
	public void draw()
	{
		//binding the texture
		glBindTexture(GL_TEXTURE_2D, tex.texRef);
		//rendering the geometry as triangles
		glBegin(GL_TRIANGLES);
		//looping through each of the elements of the vertex lists
		for(int i = 0; i < this.xCoords.size(); i += 3)
		{
			glTexCoord2f(texXCoords.get(i), texYCoords.get(i));
			glVertex3f(xCoords.get(i), yCoords.get(i), zCoords.get(i));
			glTexCoord2f(texXCoords.get(i+1), texYCoords.get(i+1));
			glVertex3f(xCoords.get(i+1), yCoords.get(i+1), zCoords.get(i+1));
			glTexCoord2f(texXCoords.get(i+2), texYCoords.get(i+2));
			glVertex3f(xCoords.get(i+2), yCoords.get(i+2), zCoords.get(i+2));
		}
		//ending the geometry data stream
		glEnd();
	}
}